﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using T.ServiceFramework.Spi;
using T.ServiceFramework.Spi.Common;
using T.ServiceComponent.Runtime.Common.Utility;

namespace T.SF.Console
{

    static class Program
    {
        private const string ConfigCenterKey = "ConfigCenter.Url";
        private static bool isShowInvokeLog = false;
        private static bool isRegLogService = true;
        private static bool isAutoRestart = false;
        // 创建一个初始状态为“未设置”的 ManualResetEventSlim
        // Wait() 方法会阻塞，直到有代码调用 Set()
        private static readonly ManualResetEventSlim _exitEvent = new ManualResetEventSlim(false);


        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        static void Main(string[] args)
        {
            // AppContext.SetSwitch("Switch.System.Runtime.Serialization.SerializationGuard.DisableBinaryFormatterSerializationGuard", true);
            System.Console.WriteLine("Welcome T Service Framework！");
            System.Console.WriteLine("HostName:" + Dns.GetHostName());
            System.Console.WriteLine("AppDomain.BaseDirectory:" + AppDomain.CurrentDomain.BaseDirectory);
            if (System.Configuration.ConfigurationManager.AppSettings.Get("IsDebug") == "true" || System.Configuration.ConfigurationManager.AppSettings.Get("IsDebug") == "1")
            {
                System.Console.WriteLine("Debug Mode, Please enter Enter to continue！");
                System.Console.ReadLine();
            }

            System.Console.WriteLine($"ConfigCenter.IsEnabled：{System.Configuration.ConfigurationManager.AppSettings.Get("ConfigCenter.IsEnabled")}");

            //从外部环境初始化信息（docker等）
            InitFromEnvironment(args);

            //AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            //AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
            // 记录环境信息
            ExitDiagnostics.LogEnvironmentInfo();

            EnhancedExitHandler.RegisterExitHandlers();
            try
            {
                //开启日志清理服务 
                LogCleanupService.StartLogCleanupTask();

                //线程池大小设置
                var maxThreads = 4096;
                var maxThreadsConfig = T.ServiceComponent.Kernel.Service.ConfigHelper.GetString("ThreadPoolMaxThreads");
                if (!string.IsNullOrEmpty(maxThreadsConfig))
                    maxThreads = Convert.ToInt32(maxThreadsConfig);

                var SetMaxThreadsSuc = ThreadPool.SetMaxThreads(maxThreads, maxThreads);
                ConsoleService.Show($"ThreadPool.SetMaxThreads：{maxThreads},{SetMaxThreadsSuc}", SetMaxThreadsSuc ? LogShowType.SuccessInfo : LogShowType.FailInfo);

                var minThreads = 1024;
                var minThreadsConfig = T.ServiceComponent.Kernel.Service.ConfigHelper.GetString("ThreadPoolMinThreads");
                if (!string.IsNullOrEmpty(minThreadsConfig))
                    minThreads = Convert.ToInt32(minThreadsConfig);

                var SetMinThreadsSuc = ThreadPool.SetMinThreads(minThreads, minThreads);
                System.Console.WriteLine($"ThreadPool.SetMinThreads：{minThreads},{SetMinThreadsSuc}", SetMinThreadsSuc ? LogShowType.SuccessInfo : LogShowType.FailInfo);


                isShowInvokeLog = T.ServiceComponent.Kernel.Service.ConfigHelper.GetBool("TSF.IsShowServiceError");
                isRegLogService = T.ServiceComponent.Kernel.Service.ConfigHelper.GetBool("TSF.IsRegLogService");

                var port = SetInParam(args);
                ShowTipsInfo();
                StartConsole(port);
            }
            catch (Exception ex)
            {
                try
                {
                    TSFLogger.Fatal(ex, "Startup failed!");
                    MonitorProvider.ReportFatalError("Startup failed!", ex);
                }
                catch (Exception e)
                {
                    System.Console.Error.WriteLine(ex);
                    System.Console.Error.WriteLine(e);
                }

                LogWithTimestamp($"Main方法异常: {ex}", LogShowType.FailInfo);
            }

            /*
             * 搜索您的代码中是否有：
                Console.ReadLine()
                Console.ReadKey()
                Console.Read()
                这些在 systemd 环境下会立即返回，可能导致程序提前退出
             */
            if (EnvironmentTools.IsUnixLikeSystem() == false)
            {
                System.Console.WriteLine("Please  click the Enter key to close！");
                System.Console.ReadLine();
            }
            else
            {
                // 在 Linux (或任何非 Windows) 系统上，我们使用 ManualResetEventSlim 来阻塞主线程
                // 这会让程序作为一个服务持续运行，而不是立即退出。
                System.Console.WriteLine("Application started as a service. Press Ctrl+C to exit.");
                _exitEvent.Wait();
                // 程序会永远停留在这里，直到进程被终止
            }
        }

        private static void InitFromEnvironment(string[] args)
        {
            /******* 1. docker容器化场景下通过环境参数获取配置中心地址 *******/
            string configCenterUrl = GetEvnParamValue("CONFIGCENTER_URL");
            if (string.IsNullOrEmpty(configCenterUrl))
            {
                configCenterUrl = ConfigurationManager.AppSettings.Get(ConfigCenterKey);
            }
            else
            {
                System.Console.WriteLine($"Get configCenterUrl param from Environment: {configCenterUrl}");
                ConfigCenterManager.SetConfigCenterUrl(configCenterUrl);
                // 向 AppSettings 注入／覆盖
                ConfigurationManager.AppSettings["ConfigCenter.Url"] = configCenterUrl;
            }
            System.Console.WriteLine($"ConfigCenter.Url：{configCenterUrl}");

            /******* 2. docker容器化场景下通过命令行参数传入hostid *******/
            string hostid = GetInputParamValue(args, "hostid");
            if (!string.IsNullOrEmpty(hostid))
            {
                System.Console.WriteLine($"Get hostId param from command line: {hostid}");
                AppConfig.SetHostId(hostid);
            }
            //如果没获取到 尝试从环境变量里获取
            else
            {
                hostid = GetEvnParamValue("HOSTID");
                if (!string.IsNullOrEmpty(hostid))
                {
                    System.Console.WriteLine($"Get hostid param from Environment: {hostid}");
                    ConfigCenterManager.SetConfigCenterUrl(hostid);
                }
            }
        }

        #region Init
        private static string SetInParam(string[] args)
        {
            if (args != null)
            {
                var item = args.FirstOrDefault(x => x.StartsWith("HSFPort:", StringComparison.OrdinalIgnoreCase));
                if (string.IsNullOrEmpty(item) == false)
                {
                    string port = item.ToLower().ToUpper().Replace("HSFPORT:", "");
                    if (string.IsNullOrEmpty(port) == false)
                        AppConfig.SetHSFHostPort(port);

                    System.Console.WriteLine("Please Enter command : " + item);
                    return port;
                }
            }

            return String.Empty;
        }

        private static void ShowTipsInfo()
        {
            CheckCanSetConsoleColor();

            System.Console.WriteLine("========================================================================================================\r\n");
            System.Console.WriteLine("******************************Welcome to T Service Framework(TSF)******************************\r\n");
            System.Console.WriteLine("========================================================================================================");

        }

        private static void StartConsole(string port)
        {
            try
            {
                TSFLogger.SetLevel(0); //启动时将日志级别调低，以便输出详细日志。
                HostController.Current.SetShowInvokeLogState(isShowInvokeLog);
                HostController.Current.OnRestart += Current_OnRestart;
                HostController.Current.Start(port);
                TSFLogger.ReSetLevel(); //启动完以后将日志级别恢复默认值。
            }
            catch (System.Exception e)
            {
                TSFLogger.Fatal(e, "StartConsole failed!");
                MonitorProvider.ReportFatalError("StartConsole failed!", e);

                if (CheckRestartTimes())
                {
                    TSFLogger.Fatal("Restarts more than 5 times within 1 minute, boot failure!");
                }
                else
                {
                    Restart("StartConsole failed!");
                }
            }

            //linux下注册为服务，不需要等待命令行输入。
            if (EnvironmentTools.IsUnixLikeSystem() == false)
            {
                while (WaitCommand() == true)
                {
                }
            }
        }

        private static void Current_OnRestart(string reason)
        {
            Restart(reason);
        }

        private static bool WaitCommand()
        {
            long userSelect = 0;

            ConsoleService.SetConsoleColor(ConsoleColor.Yellow);
            System.Console.WriteLine("Please select the command to execute.");
            System.Console.WriteLine("1. Display service information");
            if (isShowInvokeLog)
                System.Console.WriteLine("2. Disable call log");
            else
                System.Console.WriteLine("2. Enable call log");
            if (isRegLogService)
                System.Console.WriteLine("3. Disable Log service");
            else
                System.Console.WriteLine("3. Enable Log service");

            System.Console.WriteLine("4. Restart");
            System.Console.WriteLine("5. Quit");
            System.Console.WriteLine("6. Clear");
            System.Console.WriteLine("7. Test HttpHost");
            System.Console.WriteLine("8. Show LocalServicePackages");
            ConsoleService.ResetColor();

            userSelect = GetInput("Please Enter command...");
            if (userSelect == 1)
            {
                ProviderController.ShowStartResult();
            }
            else if (userSelect == 2)
            {
                isShowInvokeLog = !isShowInvokeLog;
                HostController.Current.SetShowInvokeLogState(isShowInvokeLog);
            }
            else if (userSelect == 3)
            {
                isRegLogService = !isRegLogService;
                if (isRegLogService)
                {
                    TSFLogger.SetLevel(0);
                }
                else
                {
                    TSFLogger.ReSetLevel();
                }
            }
            else if (userSelect == 4)
            {
                var userConfirm = GetInputStr("Restart not not? Y:Yes, N:No");
                if (string.Equals(userConfirm, "y", StringComparison.OrdinalIgnoreCase))
                    Restart("Restart the service manually.");
            }
            else if (userSelect == 5)
            {
                var userConfirm = GetInputStr("Quit or not? Y:Yes, N:No");
                if (string.Equals(userConfirm, "y", StringComparison.OrdinalIgnoreCase))
                {
                    HostController.Current.DisposeService();
                    return false;
                }
            }
            else if (userSelect == 6)
            {
                System.Console.Clear();
            }
            else if (userSelect == 7)
            {
                try
                {
                    HttpClient client = new HttpClient();
                    client.BaseAddress = new Uri(AppConfig.GetSGHostAddress());

                    HttpResponseMessage resp = client.GetAsync("api/demo").Result;
                    resp.EnsureSuccessStatusCode();

                    var products = resp.Content.ReadAsStringAsync().Result;
                    System.Console.WriteLine(products);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine(e);
                }
            }
            else if (userSelect == 8)
            {
                var list = ServiceFramework.Service.PackageLoadService.Current.GetServiceLastedPackages();
                if (list != null && list.Count > 0)
                {
                    foreach (var lspkg in list)
                    {
                        System.Console.WriteLine($"{lspkg.MetadataID}-{lspkg.LocalServicePath}");
                    }
                }
                else
                {
                    System.Console.WriteLine("0 Packages.");
                }
            }
            else
            {
                ConsoleService.SetConsoleColor(ConsoleColor.Yellow);
                System.Console.WriteLine("Please select the command to execute.");
                System.Console.WriteLine("1. Display service information");
                if (isShowInvokeLog)
                    System.Console.WriteLine("2. Disable call log");
                else
                    System.Console.WriteLine("2. Enable call log");
                if (isRegLogService)
                    System.Console.WriteLine("3. Disable Log service");
                else
                    System.Console.WriteLine("3. Enable Log service");

                System.Console.WriteLine("4. Restart");
                System.Console.WriteLine("5. Quit");
                System.Console.WriteLine("6. Clear");
                System.Console.WriteLine("7. Test HttpHost");
                System.Console.WriteLine("8. Show LocalServicePackages");
                ConsoleService.ResetColor();
            }


            return true;
        }

        #endregion

        #region  Exit
        //  static ControlCtrlDelegate newDelegate = new ControlCtrlDelegate(HandlerRoutine);
        private static bool HandlerRoutine(int CtrlType)
        {
            if (isAutoRestart == true)
                return false;
            switch (CtrlType)
            {
                case 0:
                    ConsoleService.Show("The program is about to be closed.", LogShowType.FailInfo);
                    HostController.Current.DisposeService();
                    System.Threading.Thread.Sleep(1000);
                    break;
                case 2:
                    ConsoleService.Show("The program is about to be closed.", LogShowType.FailInfo);
                    HostController.Current.DisposeService();
                    System.Threading.Thread.Sleep(1000);
                    break;
            }
            return false;
        }
        #endregion

        #region  Log

        private static void DisplayError(Exception e)
        {
            if (e != null)
            {
                ConsoleService.Show(e);
            }
        }

        private static void LogError(System.Exception e)
        {
            LocalErrorLogService.Write(e);
        }

        private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            try
            {
                LogProcessExit(sender, e);
                ConsoleService.Show("Process is closed.", LogShowType.FailInfo);

                //如果CMDB 为null 则直接返回。
                if (SFContext.Host == null)
                {
                    return;
                }
                LogWithTimestamp("开始执行优雅关闭...", LogShowType.FailInfo);
                ShutdownHandler.GracefulShutdown("Process is closed.");
                LogWithTimestamp("开始执行 HandlerRoutine...", LogShowType.FailInfo);
                HandlerRoutine(0);
                LogWithTimestamp("ProcessExit 处理完成", LogShowType.FailInfo);
            }
            catch(Exception ex)
            {
                LogWithTimestamp($"ProcessExit 处理异常: {ex}", LogShowType.FailInfo);
            }
        }
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            LogUnhandledException(sender, e);
            ConsoleService.Show("Unknown exception occurred in the system: " + GetExceptionInfo(e.ExceptionObject as System.Exception), LogShowType.FailInfo);

            LogError(e.ExceptionObject as System.Exception);
            Restart("Unknown exception occurred in the system: " + GetExceptionInfo(e.ExceptionObject as System.Exception));
        }

        private static string GetExceptionInfo(Exception e)
        {
            if (e == null)
                return string.Empty;

            return T.ServiceComponent.Kernel.Service.ExceptionHelper.GetExceptionDetail(e);
        }

        #endregion

        #region Color
        private static void CheckCanSetConsoleColor()
        {
            ConsoleService.CheckCanSetConsoleColor();
        }

        #endregion

        #region Tool

        public static void Restart(string reason)
        {
            if( EnvironmentTools.IsUnixLikeSystem())
            {
                RestartOnLinux(reason);
            }
            else
            {
                RestartOnWindows(reason);
            }
        }

        public static void RestartOnWindows(string reason)
        {
            try
            {
                TSFLogger.Warn("Will Restart:" + reason, false);
                WriteRestartLog(reason);
                HostController.Current.DisposeService();
                //优雅地关闭Host
                ShutdownHandler.GracefulShutdown(reason);

            }
            catch (Exception ex)
            {
                LocalErrorLogService.Write(ex);
            }
            TSFLogger.Warn("Restart after 5 seconds");
            Thread.Sleep(5000);
            string path = AppDomain.CurrentDomain.BaseDirectory;
            path = Path.Combine(path, Process.GetCurrentProcess().ProcessName) + ".exe";

            var args = Environment.GetCommandLineArgs();
            string cmdArgs = string.Empty;
            if (args != null)
                args.ForEach(x => cmdArgs += " " + x);

            var startInfo = new ProcessStartInfo
            {
                FileName = path,
                Arguments = cmdArgs,
                UseShellExecute = true,
                CreateNoWindow = false,
                WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
            };
            Process.Start(startInfo);
            Thread.Sleep(100); 
            Environment.Exit(0);
        }

        private static void RestartOnLinux(string reason)
        {
            try
            {
                TSFLogger.Warn("Application is requesting a restart. Reason: " + reason, false);
                WriteRestartLog(reason);

                // 优雅地关闭Host，释放资源
                HostController.Current.DisposeService();
                ShutdownHandler.GracefulShutdown(reason);
            }
            catch (Exception ex)
            {
                LocalErrorLogService.Write(ex);
            }
            finally
            {
                TSFLogger.Warn("Exiting with code 0 to signal systemd for restart.");
                Environment.Exit(0);
            }
        }


        internal static void WriteRestartLog(string reason)
        {
            try
            {
                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log");
                if (Directory.Exists(path) == false)
                    Directory.CreateDirectory(path);

                path = Path.Combine(path, "restart.log");
                File.AppendAllText(path, DateTime.Now.ToString() + "-" + reason + Environment.NewLine);
            }
            catch
            { }
        }


        private static long GetInput(string tips)
        {
            bool result = false;
            long lngCount = 0;
            while (result == false)
            {
                System.Console.WriteLine(tips);
                string count = System.Console.ReadLine();
                result = long.TryParse(count, out lngCount);
            }

            return lngCount;
        }

        private static string GetInputStr(string tips)
        {
            while (true)
            {
                System.Console.WriteLine(tips);
                var str = System.Console.ReadLine() ?? string.Empty;
                return str;
            }
        }

        /// <summary>
        /// 通过读取Restart.log 文件 判断 1分钟内的重启次数是否到达5次
        /// </summary>
        /// <returns></returns>
        private static bool CheckRestartTimes()
        {
            try
            {
                string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log");
                if (Directory.Exists(path) == false)
                    Directory.CreateDirectory(path);
                path = Path.Combine(path, "restart.log");
                if (File.Exists(path))
                {
                    string[] lines = File.ReadAllLines(path);
                    string[] lastLines = lines.TakeLast(5).ToArray();
                    if (lastLines.Length > 0)
                    {
                        var lastTime = DateTime.MinValue;
                        if (DateTime.TryParse(lastLines[0].Split('-')[0], out lastTime))
                        {
                            if (DateTime.Now.AddMinutes(-1) <= lastTime)
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                TSFLogger.Error(ex, "CheckRestartTimes failed!");
            }
            return false;
        }
        #endregion

        //#region Linux下分析用工具
        private static void LogUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            LogWithTimestamp("=== UnhandledException 事件触发 ===", LogShowType.FailInfo);
            LogWithTimestamp($"异常对象: {e.ExceptionObject}", LogShowType.FailInfo);
            LogWithTimestamp($"是否终止: {e.IsTerminating}", LogShowType.FailInfo);

            if (e.ExceptionObject is Exception ex)
            {
                LogWithTimestamp($"异常类型: {ex.GetType().Name}", LogShowType.FailInfo);
                LogWithTimestamp($"异常消息: {ex.Message}", LogShowType.FailInfo);
                LogWithTimestamp($"异常堆栈: {ex.StackTrace}", LogShowType.FailInfo);
            }
        }

        private static void LogProcessExit(object sender, EventArgs e)
        {
            LogWithTimestamp("=== ProcessExit 事件触发 ===", LogShowType.FailInfo);
            LogWithTimestamp($"退出代码: {Environment.ExitCode}", LogShowType.FailInfo);
            LogWithTimestamp($"当前线程ID: {Thread.CurrentThread.ManagedThreadId}", LogShowType.FailInfo);
            LogWithTimestamp($"是否在终结器线程: {Thread.CurrentThread.IsBackground}", LogShowType.FailInfo);
        }

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            LogWithTimestamp($"=== Console.CancelKeyPress 事件触发 ===", LogShowType.FailInfo);
            LogWithTimestamp($"取消类型: {e.SpecialKey}", LogShowType.FailInfo);
            LogWithTimestamp($"是否取消: {e.Cancel}", LogShowType.FailInfo);

            // 可以设置 e.Cancel = true 来阻止立即退出，进行优雅关闭
            e.Cancel = true;

            Task.Run(() =>
            {
                LogWithTimestamp("开始优雅关闭程序...", LogShowType.FailInfo);
                try
                {
                    ShutdownHandler.GracefulShutdown("Console cancel key pressed.");
                    HandlerRoutine(0);
                }
                catch (Exception ex)
                {
                    LogWithTimestamp($"优雅关闭异常: {ex}", LogShowType.FailInfo);
                }
                finally
                {
                    Environment.Exit(0);
                }
            });
        }

        // 增强的日志记录方法
        private static void LogWithTimestamp(string message, LogShowType logType)
        {
            ExitDiagnostics.LogWithTimestamp(message, logType);
        }

        private static string GetInputParamValue(string[] args, string paramName)
        {
            foreach (var arg in args)
            {
                if (arg.StartsWith($"--{paramName}="))
                {
                    return arg.Substring($"--{paramName}=".Length);
                }
            }

            return string.Empty; // 默认值
        }

        private static string GetEvnParamValue(string paramName)
        {
            // 直接读取环境变量，环境变量默认大写
            var result = Environment.GetEnvironmentVariable(paramName.ToUpper())
                         ?? string.Empty;
            return result;
        }

        public static class ExitDiagnostics
        {
            public static void LogSystemInfo()
            {
                var process = Process.GetCurrentProcess();
                LogWithTimestamp($"进程信息:", LogShowType.GeneralInfo);
                LogWithTimestamp($"  PID: {process.Id}", LogShowType.GeneralInfo);
                LogWithTimestamp($"  启动时间: {process.StartTime}", LogShowType.GeneralInfo);
                LogWithTimestamp($"  CPU时间: {process.TotalProcessorTime}", LogShowType.GeneralInfo);
                LogWithTimestamp($"  内存使用: {process.WorkingSet64 / 1024 / 1024} MB", LogShowType.GeneralInfo);
                LogWithTimestamp($"  线程数: {process.Threads.Count}", LogShowType.GeneralInfo);
                LogWithTimestamp($"  句柄数: {process.HandleCount}", LogShowType.GeneralInfo);

                // 线程信息
                LogWithTimestamp($"活动线程:", LogShowType.GeneralInfo);
                foreach (ProcessThread thread in process.Threads)
                {
                    LogWithTimestamp($"  Thread {thread.Id}: {thread.ThreadState}", LogShowType.GeneralInfo);
                }
            }

            public static void LogEnvironmentInfo()
            {
                LogWithTimestamp("=== 环境信息 ===", LogShowType.GeneralInfo);
                LogWithTimestamp($"当前目录: {Environment.CurrentDirectory}", LogShowType.GeneralInfo);
                LogWithTimestamp($"程序集位置: {Assembly.GetExecutingAssembly().Location}", LogShowType.GeneralInfo);
                LogWithTimestamp($"用户: {Environment.UserName}", LogShowType.GeneralInfo);
                LogWithTimestamp($"机器名: {Environment.MachineName}", LogShowType.GeneralInfo);
                LogWithTimestamp($"OS版本: {Environment.OSVersion}", LogShowType.GeneralInfo);
                LogWithTimestamp($"是否交互模式: {Environment.UserInteractive}", LogShowType.GeneralInfo);
                LogWithTimestamp($"命令行参数: {string.Join(" ", Environment.GetCommandLineArgs())}", LogShowType.GeneralInfo);

                // 记录关键环境变量
                var importantVars = new[] { "PATH", "HOME", "USER", "DOTNET_ROOT", "ASPNETCORE_ENVIRONMENT" };
                foreach (var varName in importantVars)
                {
                    var value = Environment.GetEnvironmentVariable(varName);
                    LogWithTimestamp($"环境变量 {varName}: {value ?? "未设置"}", LogShowType.GeneralInfo);
                }

                // 记录程序集加载信息
                LogWithTimestamp("已加载程序集:", LogShowType.GeneralInfo);
                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    LogWithTimestamp($"  {assembly.FullName}", LogShowType.GeneralInfo);
                }

                CheckConsoleDependencies();
            }

            public static void CheckConsoleDependencies()
            {
                LogWithTimestamp("=== 控制台依赖检查 ===", LogShowType.GeneralInfo);

                // 检查是否有控制台输入依赖
                LogWithTimestamp($"控制台可用: {System.Console.IsInputRedirected == false}", LogShowType.GeneralInfo);
                LogWithTimestamp($"输入重定向: {System.Console.IsInputRedirected}", LogShowType.GeneralInfo);
                LogWithTimestamp($"输出重定向: {System.Console.IsOutputRedirected}", LogShowType.GeneralInfo);
                LogWithTimestamp($"错误重定向: {System.Console.IsErrorRedirected}", LogShowType.GeneralInfo);

                // 检查是否有阻塞的控制台读取
                // 搜索代码中的 Console.ReadLine(), Console.ReadKey() 等
            }

            // 增强的日志记录方法
            internal static void LogWithTimestamp(string message, LogShowType logType)
            {
                var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                var threadId = Thread.CurrentThread.ManagedThreadId;
                var fullMessage = $"[{timestamp}] [Thread:{threadId}] {message}";

                //ConsoleService.Show(fullMessage, logType);

                // 如果可能的话，也写入到文件日志
                try
                {
                    var exitLogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "tsf_exit_debug", "tsf_exit_debug.log");
                    if (!Directory.Exists(Path.GetDirectoryName(exitLogPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(exitLogPath));
                    }
                    // 假设您有文件日志记录功能
                    File.AppendAllText(exitLogPath, fullMessage + Environment.NewLine);
                }
                catch
                {
                    // 忽略文件写入错误
                }
            }
        }

        // 退出原因跟踪器
        public static class ExitReasonTracker
        {
            private static readonly ConcurrentQueue<string> _exitReasons = new();
            private static volatile bool _isShuttingDown = false;
            private static readonly object _lock = new();

            // 记录退出原因
            public static void RecordExitReason(string reason, string location = null)
            {
                var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                var threadId = Thread.CurrentThread.ManagedThreadId;
                var stackTrace = Environment.StackTrace;

                var fullReason = $"[{timestamp}] [Thread:{threadId}] {reason}";
                if (!string.IsNullOrEmpty(location))
                {
                    fullReason += $" | Location: {location}";
                }

                _exitReasons.Enqueue(fullReason);

                // 同时记录到日志
                LogWithTimestamp($"EXIT_REASON: {fullReason}", LogShowType.FailInfo);

                // 记录调用堆栈（前10层）
                var lines = stackTrace.Split('\n');
                for (int i = 0; i < Math.Min(10, lines.Length); i++)
                {
                    if (!string.IsNullOrWhiteSpace(lines[i]))
                    {
                        LogWithTimestamp($"  STACK[{i}]: {lines[i].Trim()}", LogShowType.FailInfo);
                    }
                }
            }

            // 标记正在关闭
            public static void MarkShuttingDown(string reason)
            {
                lock (_lock)
                {
                    if (!_isShuttingDown)
                    {
                        _isShuttingDown = true;
                        RecordExitReason($"SHUTDOWN_INITIATED: {reason}");
                    }
                }
            }

            // 获取所有退出原因
            public static string[] GetAllExitReasons()
            {
                var reasons = new List<string>();
                while (_exitReasons.TryDequeue(out var reason))
                {
                    reasons.Add(reason);
                }
                return reasons.ToArray();
            }

            // 检查是否正在关闭
            public static bool IsShuttingDown => _isShuttingDown;
        }

        // 增强的退出处理器
        public static class EnhancedExitHandler
        {
            private static readonly CancellationTokenSource _shutdownCts = new();
            private static TaskCompletionSource<bool> _mainTaskCompletion = new();

            public static void RegisterExitHandlers()
            {
                // 1. ProcessExit - 只能获取到很少的信息
                AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
                {
                    LogWithTimestamp("=== ProcessExit 事件触发 ===", LogShowType.FailInfo);
                    LogWithTimestamp($"Exit Code: {Environment.ExitCode}", LogShowType.FailInfo);
                    LogWithTimestamp($"HasShutdownStarted: {Environment.HasShutdownStarted}", LogShowType.FailInfo);
                    LogWithTimestamp($"当前进程ID: {Process.GetCurrentProcess().Id}", LogShowType.FailInfo);
                    LogWithTimestamp($"工作集: {Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024} MB", LogShowType.FailInfo);

                    // ProcessExit 的限制：
                    // - 不能知道是谁调用了 Environment.Exit()
                    // - 不能知道是否是因为未处理异常
                    // - 不能知道是否是外部信号
                    // - 只有 ExitCode 信息（通常是0表示正常退出）

                    // 显示我们收集的退出原因
                    var reasons = ExitReasonTracker.GetAllExitReasons();
                    if (reasons.Length > 0)
                    {
                        LogWithTimestamp("收集到的退出原因:", LogShowType.FailInfo);
                        foreach (var reason in reasons)
                        {
                            LogWithTimestamp($"  {reason}", LogShowType.FailInfo);
                        }
                    }
                    else
                    {
                        LogWithTimestamp("未收集到明确的退出原因", LogShowType.FailInfo);
                        LogWithTimestamp("可能的原因:", LogShowType.FailInfo);
                        LogWithTimestamp("  1. Main方法执行完毕自然退出", LogShowType.FailInfo);
                        LogWithTimestamp("  2. 某处调用了Environment.Exit()但未记录", LogShowType.FailInfo);
                        LogWithTimestamp("  3. 未处理的异常导致程序崩溃", LogShowType.FailInfo);
                        LogWithTimestamp("  4. 外部信号（如systemd发送的SIGTERM）", LogShowType.FailInfo);
                    }

                    // 尝试优雅关闭
                    try
                    {
                        if (SFContext.Host != null)
                        {
                            ShutdownHandler.GracefulShutdown("ProcessExit event triggered");
                        }
                        HandlerRoutine(0);
                        // 解锁主线程，让 Main 方法可以优雅地结束。
                        // 这是一个好习惯，确保了逻辑的完整性。
                        _exitEvent.Set();
                    }
                    catch (Exception ex)
                    {
                        LogWithTimestamp($"ProcessExit处理异常: {ex}", LogShowType.FailInfo);
                    }
                };

                // 2. 未处理异常
                AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
                {
                    ExitReasonTracker.RecordExitReason(
                        $"未处理异常: {e.ExceptionObject}",
                        "AppDomain.UnhandledException"
                    );

                    Restart("Unknown exception occurred in the system: " + GetExceptionInfo(e.ExceptionObject as System.Exception));
                };

                // 3. Console取消事件
                System.Console.CancelKeyPress += (sender, e) =>
                {
                    ExitReasonTracker.RecordExitReason(
                        $"Console取消键: {e.SpecialKey}",
                        "Console.CancelKeyPress"
                    );
                };

                // 4. Task异常
                TaskScheduler.UnobservedTaskException += (sender, e) =>
                {
                    ExitReasonTracker.RecordExitReason(
                        $"未观察Task异常: {e.Exception}",
                        "TaskScheduler.UnobservedTaskException"
                    );
                };

                // 5. Linux信号
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    RegisterUnixSignals();
                }
            }

            private static void RegisterUnixSignals()
            {
                try
                {
                    PosixSignalRegistration.Create(PosixSignal.SIGTERM, context =>
                    {
                        ExitReasonTracker.RecordExitReason(
                            "收到SIGTERM信号（通常由systemd发送）",
                            "PosixSignal.SIGTERM"
                        );
                        ExitReasonTracker.MarkShuttingDown("SIGTERM signal received");
                        context.Cancel = true;

                        Task.Run(async () =>
                        {
                            await GracefulShutdownAsync("SIGTERM");
                            Environment.Exit(0);
                        });
                    });

                    PosixSignalRegistration.Create(PosixSignal.SIGINT, context =>
                    {
                        ExitReasonTracker.RecordExitReason(
                            "收到SIGINT信号（Ctrl+C）",
                            "PosixSignal.SIGINT"
                        );
                        ExitReasonTracker.MarkShuttingDown("SIGINT signal received");
                        context.Cancel = true;

                        Task.Run(async () =>
                        {
                            await GracefulShutdownAsync("SIGINT");
                            Environment.Exit(0);
                        });
                    });

                }
                catch (Exception ex)
                {
                    ExitReasonTracker.RecordExitReason($"注册Unix信号失败: {ex}", "RegisterUnixSignals");
                }
            }

            // 优雅关闭
            private static async Task GracefulShutdownAsync(string reason)
            {
                try
                {
                    if (SFContext.Host != null)
                    {
                        ShutdownHandler.GracefulShutdown($"Graceful shutdown: {reason}");
                    }

                    // 给一些时间让日志写入
                    await Task.Delay(500);
                }
                catch (Exception ex)
                {
                    ExitReasonTracker.RecordExitReason($"优雅关闭异常: {ex}", "GracefulShutdownAsync");
                }
            }

        }
        //#endregion
    }
}
